home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / blix / haeberlifont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  12.5 KB  |  615 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*_______________________________________________________________________
  18.  |
  19.  | haeberlifont.c - support for polygonal fonts
  20.  |
  21.  | This is for 99% created by using cut & paste from files from Paul
  22.  | Haeberli. Originally the support was for much more then is in this
  23.  | file. I only needed the routines for polygonal fonts. Prototypes
  24.  | were added.
  25.  |
  26.  | Frans van Hoesel, Xtreme Graphics Software
  27.  |
  28. */
  29.  
  30.  
  31.  
  32. /*
  33.  * Copyright (C) 1991, Silicon Graphics, Inc.
  34.  * All Rights Reserved.
  35.  */
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <malloc.h>
  39. #include <gl/gl.h>
  40. #include <bstring.h>
  41.  
  42. #include "haeberlifont.h"
  43.  
  44. #define OFMAGIC        0x93339333
  45.  
  46. #define TM_TYPE        1
  47. #define PO_TYPE        2
  48. #define SP_TYPE        3
  49.  
  50. /* ops for poly characters */
  51.  
  52. #define    PO_BGNLOOP    (1)
  53. #define    PO_ENDBGNLOOP    (2)
  54. #define    PO_RETENDLOOP    (3)
  55. #define    PO_RET        (4)
  56.  
  57. static void drawglyph(glyph *g);
  58. static void out_scanline(int y);
  59. static void out_span(int xmin, int xmax);
  60. static void execcharprog(short *sptr, int xmin, int ymin, float cscale);
  61. static Edge *newedge(void);
  62. static void freeedge( Edge *e );
  63. static void do_beginfacet(void);
  64. static void do_endfacet(void);
  65. static void do_vertex(float x, float y);
  66. static void createedge(Edge *e1, Edge *e2);
  67. static void myremoveoldspans(float y);
  68. static int chartoindex(objfnt *fnt, int c);
  69. static void createglyph(chardesc *cd, glyph *g);
  70. static void do_beginscan(int ylines);
  71. static void do_endscan(void);
  72. static void bmfree(Bitmap *b);
  73. static Bitmap *bmnew(int xsize, int ysize);
  74. static int bmrasbytes(Bitmap *b);
  75. static void bmpos(float xpos, float ypos);
  76. static void mydrawbitmap(Bitmap *bm);
  77.  
  78. #define CDEL        (30)
  79. #define MALLOCBYTES    (200000)
  80.  
  81. static unsigned char *thecountmap;
  82. static unsigned char *bmbase;
  83. static int xpix, ypix;
  84. static float cscale, curxpos, curypos;
  85. static unsigned long maptab[65];
  86. static unsigned long map3[65];
  87. static glyph *glyphcache;
  88. static long c1  = 0x0000FFFF;
  89. static long c2  = 0x000000FF;
  90.  
  91. void charsetcolors(long col1, long col2) {
  92.     c1 = col1;
  93.     c2 = col2;
  94. }
  95.  
  96. unsigned char *mymalloc(int n) {
  97.     unsigned char *cptr;
  98.  
  99.     cptr = (unsigned char *)malloc(n);
  100.     if(!cptr) {
  101.      fprintf(stderr,"malloc can't get %d bytes\n",n);
  102.      exit(1);
  103.     }
  104.     return cptr;
  105. }
  106.  
  107.  
  108. void glyphinit(objfnt *fnt) {
  109.     int i, c, m3;
  110.  
  111.     glyphcache = (glyph *)mymalloc(fnt->nchars*sizeof(glyph));
  112.     bzero(glyphcache,fnt->nchars*sizeof(glyph));
  113.     thecountmap = (unsigned char *)mymalloc(MALLOCBYTES);
  114.     for(i=0; i<=64; i++) {
  115.     c = 255-(i*355)/64;
  116.     if(c<(85-CDEL)) {
  117.        c = 0;
  118.        m3 = 2;
  119.     } else if(c>(170+CDEL)) {
  120.        c = 255;
  121.        m3 = 0;
  122.     } else {
  123.        c = 128;
  124.        m3 = 1;
  125.      }
  126.         maptab[i] = 0x10101*c;
  127.         map3[i] = m3;
  128.     }
  129. }
  130.  
  131. void get_charpos(float *x, float *y) {
  132.     *x = curxpos;
  133.     *y = curypos;
  134. }
  135.  
  136. void aafontmoveto(float xpos, float ypos) {
  137.     curxpos = xpos;
  138.     curypos = ypos;
  139. }
  140.  
  141. void aafontsetsize(objfnt *fnt, float pixhigh) {
  142.     cscale = (8.0*pixhigh)/fnt->scale;
  143. }
  144.  
  145.  
  146. void drawaafntchar(objfnt *fnt, int c) {
  147.     int index;
  148.     chardesc *cd;
  149.     glyph *g;
  150.  
  151.     if(!glyphcache) 
  152.     glyphinit(fnt);
  153.     index = chartoindex(fnt,c);
  154.     if(index>=0) {
  155.     g = glyphcache+index;
  156.     if(g->cscale != cscale) {
  157.         cd = fnt->chars+index;
  158.         createglyph(cd,g);
  159.     }
  160.     drawglyph(g);
  161.     }
  162. }
  163.  
  164. static void createglyph(chardesc *cd, glyph *g) {
  165.     int xmin, ymin;
  166.     int xorg, yorg;
  167.     int x, y;
  168.     int xsize, ysize;
  169.     unsigned char *cptr;
  170.     short *sptr0;
  171.     short *sptr1;
  172.     unsigned short sbit;
  173.  
  174.     if(cd->data) {
  175.     xmin = cscale*cd->llx;
  176.     ymin = cscale*cd->lly;
  177.     xmin = ((xmin+8000)&0xfffff8)-8000;
  178.     ymin = ((ymin+8000)&0xfffff8)-8000;
  179.     xorg = -xmin/8;
  180.     yorg = -ymin/8;
  181.     xsize = 8+(cscale*(cd->urx-cd->llx+1));
  182.     ysize = 8+(cscale*(cd->ury-cd->lly+1));
  183.     xpix = ((xsize-1)/8)+1;
  184.     ypix = ((ysize-1)/8)+1;
  185.     if((xpix*(ypix+1))>MALLOCBYTES) {
  186.         fprintf(stderr,"increase MALLOCBYTES\n");
  187.         exit(1);
  188.     }
  189.     bzero(thecountmap,xpix*ypix);
  190.     do_beginscan(ysize);
  191.     execcharprog(cd->data,xmin,ymin,cscale);
  192.     do_endscan();
  193.     } else {
  194.     xpix = 0;
  195.     ypix = 0;
  196.     xorg = 0;
  197.     yorg = 0;
  198.     }
  199.     if(g->bm0) {
  200.     bmfree(g->bm0);
  201.     g->bm0 = 0;
  202.     bmfree(g->bm1);
  203.     g->bm1 = 0;
  204.     }
  205.     g->movex = (cd->movex*cscale)/8.0;
  206.     g->cscale = cscale;
  207.     if(xpix>0 && ypix>0) {
  208.     g->bm0 = bmnew(xpix,ypix); 
  209.     g->bm0->xorig = xorg;
  210.     g->bm0->yorig = yorg;
  211.     g->bm1 = bmnew(xpix,ypix); 
  212.     g->bm1->xorig = xorg;
  213.     g->bm1->yorig = yorg;
  214.     cptr = thecountmap;
  215.     for(y=0; y<ypix; y++) {
  216.         sptr0 = g->bm0->base+y*g->bm0->sper;
  217.         sptr1 = g->bm1->base+y*g->bm1->sper;
  218.         sbit = 0x8000;
  219.         for(x=0; x<xpix; x++) {
  220.         switch(map3[*cptr++]) {
  221.             case 1:
  222.             *sptr0 |= sbit;
  223.             break;
  224.             case 2:
  225.             *sptr1 |= sbit;
  226.             break;
  227.         }
  228.         sbit = (sbit>>1);
  229.         if(!sbit) {
  230.             sbit = 0x8000;
  231.             sptr0++;
  232.             sptr1++;
  233.         }
  234.         }
  235.     }
  236.     }
  237. }
  238.  
  239. static void drawglyph(glyph *g) {
  240.  
  241.     if(g->bm0) {
  242.     bmpos(curxpos,curypos);
  243.     cpack(c1);
  244.     mydrawbitmap(g->bm0);
  245.     cpack(c2);
  246.     mydrawbitmap(g->bm1);
  247.     }
  248.     curxpos += g->movex;
  249.     curypos += g->movey;
  250. }
  251.  
  252. static void out_scanline(int y) {
  253.     bmbase = thecountmap+((y/8)*xpix);
  254. }
  255.  
  256. static void out_span(int xmin, int xmax) {
  257.     int x, x8, pxmin, pxmax;
  258.     int count;
  259.     unsigned char *cptr;
  260.  
  261.     pxmin = xmin>>3;
  262.     pxmax = xmax>>3;
  263.     x8 = pxmin<<3;
  264.     cptr = bmbase+pxmin;
  265.     for(x=pxmin; x<=pxmax; x++) {
  266.     if(xmin<=x8)
  267.         count = 8;
  268.     else
  269.         count = 8-xmin+x8;
  270.     if(xmax<(x8+7))
  271.         count -= ((x8+7)-xmax);
  272.     *cptr += count;
  273.     x8 += 8;
  274.     cptr++;
  275.     }
  276. }
  277.  
  278. static void execcharprog(short *sptr, int xmin, int ymin, float c_scale) {
  279.     int nverts;
  280.     float fx, fy;
  281.  
  282.     while(1) {
  283.     switch(*sptr++) {    
  284.         case PO_BGNLOOP:
  285.         do_beginfacet();
  286.         break;
  287.         case PO_ENDBGNLOOP:
  288.         do_endfacet();
  289.         do_beginfacet();
  290.         break;
  291.         case PO_RETENDLOOP:
  292.         do_endfacet();
  293.         return;
  294.         case PO_RET:
  295.         return;
  296.     }
  297.     nverts = *sptr++;
  298.     while(nverts--) {
  299.         fx = c_scale*(sptr[0])-xmin;
  300.         fy = c_scale*(sptr[1])-ymin;
  301.         do_vertex(fx,fy);
  302.         sptr+=2;
  303.     }
  304.     }
  305. }
  306.  
  307. static float bmxpos, bmypos;
  308.  
  309. static void mydrawbitmap(Bitmap *bm) {
  310.     int ixpos, iypos, scanx;
  311.     int x, y, sper, ysize;
  312.     short *sptr;
  313.  
  314.     ixpos = bmxpos-bm->xorig;
  315.     iypos = bmypos-bm->yorig;
  316.     ysize = bm->ysize;
  317.     sper = bm->sper;
  318.     linewidth(1);
  319.     sptr = bm->base;
  320.     for(y=0; y<ysize; y++) {
  321.     scanx = ixpos;
  322.     for(x=0; x<sper; x++) {
  323.         if(*sptr) {
  324.         deflinestyle(1,*sptr++);
  325.         setlinestyle(1);
  326.         move2i(scanx+15,iypos);
  327.         draw2i(scanx,iypos);
  328.         } else 
  329.            sptr++;
  330.         scanx+=16;
  331.     }
  332.     iypos++;
  333.     }
  334.     setlinestyle(0);
  335. }
  336.  
  337. static void bmpos(float xpos, float ypos) {
  338.     bmxpos = xpos;
  339.     bmypos = ypos;
  340.     cmov2(xpos,ypos);
  341. }
  342.  
  343. #define NBUCKETS    20
  344. #define TOLERANCE    0.0000001
  345. #define NINCHUNK    40
  346.  
  347. static Edge *edges, *active, *fedges;
  348. static Edge *buckets[NBUCKETS];
  349. static int npoints;
  350. static Edge start, current, last;
  351. static int scrymax;
  352.  
  353. static Edge *newedge(void) {
  354.     register Edge *e;
  355.     register int i;
  356.  
  357.     if(!fedges) {
  358.            e = (Edge *)mymalloc(NINCHUNK*sizeof(Edge));
  359.         for(i=0; i<NINCHUNK; i++)
  360.         freeedge(e++);
  361.     }
  362.     e = fedges;
  363.     fedges = fedges->next;
  364.     return e;
  365. }
  366.  
  367. static void freeedge( Edge *e ) {
  368.    if( e ) {
  369.        e->next = fedges;
  370.        fedges = e;
  371.    }
  372. }
  373.  
  374. static void do_beginfacet(void) {
  375.     npoints = 0;
  376. }
  377.  
  378. static void do_endfacet(void) {
  379.     if(npoints>0)
  380.     createedge(&last,&start);
  381. }
  382.  
  383. static void do_vertex(float x, float y) {
  384.     if(npoints++ == 0) {
  385.     start = current;
  386.     start.x = x;
  387.     start.y = y;
  388.     last = start;
  389.     } else  {
  390.     current.x = x;
  391.     current.y = y;
  392.     createedge(&last,¤t);
  393.     last = current;
  394.     }
  395. }
  396.  
  397. static void createedge(Edge *e1, Edge *e2) {
  398.     register Edge *top, *bot;
  399.     register Edge *e, *b;
  400.     int bucketno;
  401.     register float ystart;
  402.     register float dy, ady;
  403.  
  404.     if(e1->y>e2->y) {
  405.     top = e1;
  406.     bot = e2;
  407.     } else {
  408.     top = e2;
  409.     bot = e1;
  410.     }
  411.     ady = dy = top->y-bot->y;
  412.     if(ady<0.0)
  413.        ady = 0.0;
  414.     if(ady < TOLERANCE)
  415.     return;
  416.     if(top->y<=0 || bot->y>=scrymax)
  417.     return;
  418.     e = newedge();
  419.     e->ymax = top->y;
  420.     e->ymin = bot->y;
  421.     e->dxdy = (top->x-bot->x)/dy;
  422.     e->x = bot->x;
  423.     bucketno = (bot->y)*NBUCKETS/scrymax;
  424.     if(bucketno<0) bucketno = 0;
  425.     if(bucketno>=NBUCKETS) bucketno = NBUCKETS-1;
  426.     b = (Edge *)&buckets[bucketno];
  427.     ystart = e->ymin; 
  428.     while(b->next && (ystart > b->next->ymin)) 
  429.     b = b->next;
  430.     e->next = b->next;  
  431.     b->next = e;  
  432. }
  433.  
  434. static void do_beginscan(int ylines) {
  435.     int i;
  436.  
  437.     scrymax = ylines;
  438.     edges = NULL;
  439.     active = NULL;
  440.     for(i=0; i<NBUCKETS; i++)
  441.     buckets[i] = NULL;
  442. }
  443.  
  444. static void do_endscan(void) {
  445.     Edge *llast, *span, *temp, *newspan;
  446.     int i, iy, xchg, x1, x2;
  447.     float y;
  448.  
  449.     edges = NULL;
  450.     llast = (Edge *)&edges;
  451.     for(i=0; i<NBUCKETS; i++) {
  452.     if( (span=buckets[i]) != NULL ) {
  453.         llast->next = span;
  454.         while(span->next) 
  455.         span = span->next;
  456.         llast = span; 
  457.     }
  458.     }
  459.     for(iy=0; iy<scrymax; iy++) {
  460.     y = iy;
  461.  
  462.     /* remove old spans */
  463.     myremoveoldspans(y);
  464.  
  465.     /* add new spans */
  466.     temp = edges;
  467.     while(temp && (temp->ymin <= y)) {
  468.         newspan = temp;
  469.         temp = temp->next;
  470.         if(newspan->ymax > y) {
  471.         newspan->x -= newspan->dxdy * (newspan->ymin - y);
  472.         span = (Edge *)&active; 
  473.         while(span->next && (span->next->x < newspan->x) )
  474.             span = span->next;
  475.         newspan->next = span->next;
  476.         span->next = newspan;
  477.         }
  478.     }
  479.     edges = temp;
  480.  
  481.     /* order spans */
  482.     if(active) {
  483.         do {
  484.         xchg = 0;
  485.         span = (Edge *)&active; 
  486.         while(span->next && span->next->next) {
  487.             while(span->next->next ) { 
  488.             if (span->next->x > span->next->next->x) {
  489.                 temp = span->next;
  490.                 span->next = temp->next;
  491.                 temp->next = temp->next->next;
  492.                 span->next->next = temp;
  493.                 xchg++;
  494.             }
  495.             span=span->next;
  496.             }
  497.             span=span->next;
  498.         }
  499.         } while( xchg );
  500.  
  501.         /* fill spans */
  502.         out_scanline(iy);
  503.         for(span=active; span && span->next; span=span->next->next) {
  504.         x1 = span->x; x2 = span->next->x;
  505.         out_span(x1,x2);
  506.         }
  507.  
  508.         /* increment spans */
  509.         for( span = active; span; span = span->next ) 
  510.         span->x += (span->dxdy);
  511.     }
  512.     }
  513.     while(active) {
  514.     temp = active;
  515.     active = active->next;
  516.     freeedge(temp);
  517.     }
  518.     while(edges) {
  519.     temp = edges;
  520.     edges = edges->next;
  521.     freeedge(temp);
  522.     }
  523. }
  524.  
  525. static void myremoveoldspans(float y) {
  526.     register Edge *span, *temp;
  527.  
  528.     for( span = (Edge *)&active; span->next; )  {
  529.     if (span->next->ymax <= y) {
  530.         temp = span->next;
  531.         span->next = temp->next;
  532.         freeedge(temp);
  533.     } else
  534.         span = span->next;
  535.     }
  536. }
  537.  
  538.  
  539. static Bitmap *bmnew(int xsize, int ysize) {
  540.     register Bitmap *b;
  541.  
  542.     b = (Bitmap *)mymalloc(sizeof(Bitmap));
  543.     b->xsize = xsize;
  544.     b->ysize = ysize;
  545.     b->xorig = 0;
  546.     b->yorig = 0;
  547.     b->xmove = 0;
  548.     b->ymove = 0;
  549.     if(b->ysize>0 && b->ysize>0) {
  550.     b->sper = 1+((b->xsize-1)>>4);
  551.     b->base = (short *)mymalloc(bmrasbytes(b)); 
  552.     bzero(b->base,bmrasbytes(b));
  553.     } else {
  554.     b->sper = 0;
  555.     b->xsize = 0;
  556.     }
  557.     return b;
  558. }
  559.  
  560. static void bmfree(Bitmap *b){
  561.     if(b->base)
  562.     free(b->base);
  563.     free(b);
  564. }
  565.  
  566.  
  567. static int bmrasbytes(Bitmap *b) {
  568.     return b->ysize*2*b->sper;
  569. }
  570.  
  571. static int chartoindex(objfnt *fnt, int c) {
  572.     if(c<fnt->charmin)
  573.     return -1;
  574.     if(c>fnt->charmax)
  575.     return -1;
  576.     return c-fnt->charmin;
  577. }
  578.  
  579.  
  580. objfnt *readobjfnt(char *name) {
  581.     FILE *inf;
  582.     objfnt *fnt;
  583.     short *sptr;
  584.     int i;
  585.     long magic;
  586.  
  587.     inf = fopen(name,"r");
  588.     if(!inf) {
  589.     fprintf(stderr,"readobjfnt: can't open input file %s\n",name);
  590.     return 0;
  591.     }
  592.     fread(&magic,sizeof(long),1,inf);
  593.     if(magic != OFMAGIC) {
  594.     fprintf(stderr,"readobjfnt: bad magic nuber\n");
  595.     return 0;
  596.     }
  597.     fnt = (objfnt *)mymalloc(sizeof(objfnt));
  598.     fread(fnt,sizeof(objfnt),1,inf);
  599.     fnt->freeaddr = 0;
  600.     fnt->chars = (chardesc *)mymalloc(fnt->nchars*sizeof(chardesc));
  601.     fread(fnt->chars,fnt->nchars*sizeof(chardesc),1,inf);
  602.     for(i=0; i<fnt->nchars; i++) {
  603.     if(fnt->chars[i].datalen>0) {
  604.         sptr = (short *)mymalloc(fnt->chars[i].datalen);
  605.         fnt->chars[i].data = sptr;
  606.         fread(sptr,fnt->chars[i].datalen,1,inf);
  607.     } else {
  608.         fnt->chars[i].data = 0;
  609.     }
  610.     }
  611.     fclose(inf);
  612.     return fnt;
  613. }
  614.  
  615.